Code Patterns
The method
Exercises
写一些C语言小程序,然后用汇编重写,不断缩小代码大小。无实际意义,因最新的编译器优化效率很高,但能深入理解汇编和程序。
Optimization levels and debug information
典型的编译器有三种优化水平,0代表不优化
编译器还会产生一些debug信息在结果文件中
Some basics
A short introduction to the CPU
- ISA instruction set architecture
X86 ISA是可变长指令,所以随着64位处理器产生指令变化很少。
ARM ISA是定长指令,定长的优点是可以方便的计算下一个指令地址
- 4 bytes的ARM mode,2 bytes的Thumb mode,Thumb不能够满足部分4 bytes指令,产生了Thumb-2在Thumb基础上扩展了指令,支持新的4 bytes的指令,随后又出现了ARM-64使用固定长度4bytes。
- ARM 、Thumb(Thumb-2)、ARM64属于不同的指令架构,一个指令集并非另一个的变种。
- GPR General Purpose Registers(X86=16,ARM=16)
Numeral Systems
decimal numbers d结尾
binary numbers 0b开头或b结尾
hexadecimal numbers 0x开头或h结尾
octal numbers 0开头
整除问题的巧用
类比十进制数后0的个数,可以被相应10的倍数整除
二级制数或八进制或十六进制类比,如PE文件中地址十六进制表示0x41000、0x10001000,可以被0x1000(4096)整除,因为PE section被划分为4096 bytes块大小。
An Empty Function
1 | void f() |
X86:
1 | f: |
Returning Values
1 | int f() |
X86:1
2
3f:
mov eax, 123
ret
Hello, world!
1 |
|
X86:
1 | CONST SEGMENT |
IDA:
1 | main proc near |
5行and esp, 0FFFFFFF0h
这条指令该指令对齐在16字节边界在ESP寄存器中的值。这导致堆栈对准的所有值。(??对齐原理? ?)
11行leave
等于mov esp,ebp
和pop ebp
GCC (AT&T):
1 | .LC0: |
Intel与AT&T语法区别:
操作数位置相反
In Intel-syntax:
在操作数中添加”=”
AT&T syntax:
在操作数中添加“→”
寄存器前加%,立即数前加$
操作后缀添加大小
b — byte (8 bits)
w — word (16 bits)
l — long (32 bits)
q — quad (64 bits)
地址描述方式AT&T采用(),Intel采用[],寻址方式也不同。
MSVC:X86-64
1 | $SG2989 DB 'hello, world', 0AH, 00H |
In Win64, 4 function arguments are passed in the RCX , RDX , R8 , and R9 registers
GCC:X86-64
1 | .string "hello, world\n" |
The first 6 arguments are passed in the RDI , RSI , RDX , RCX , R8 , and R9 registers, and the rest—via the stack.
64-bit 模式下,写入低32bit寄存器,高32bits被清零。
Function prologue and epilogue
prologue:
1 | push ebp |
epilogue:
1 | mov esp, ebp |
stack
主要理解push和pop,sp和bp